-module(start).
-export([init/2, init_two/0]).
-include("cell_records.hrl").

%% start all processes witch represent map cells
%% Width & Height - map size
init(Width, Height) ->
  init(0, Width, Height, [], []).

%% creates two connected cells, fun only for debugging
init_two() ->
  One = cell:init_cell(0,0,#nbors{}),
  register(one, One),
  register(two, cell:init_cell(0,1,#nbors{count = 1, lower=#neighbor{npid=One}})),
  control ! {first, one}.

%% Col_number: column number, counted from 0 up to (Width - 1)
%% LN: left neighbors; list of cells pids from last created column
%% returns list of initialized cells
init(Col_num, Width, Height, LN, Initialized) when Col_num < Width - 1 ->
  Next_LN = init_column(Col_num, Height, LN),
  init(Col_num + 1, Width, Height, Next_LN, lists:append(Next_LN, Initialized));
init(Col_num, _Width, Height, LN, Initialized) ->
  lists:append(init_column(Col_num, Height, LN), Initialized).


%%% group of functions to initialize columns

%% starts one column
%% returns list of started cells
% first column
init_column(0, Height, []) ->
  init_first_column(0, 0, Height, [], []);
% odd case
init_column(Col_num, Height, LN) when Col_num rem 2 == 1 ->
  init_odd_column(Col_num, Height - 1, Height, LN, []);
% even case
init_column(Col_num, Height, LN) ->
  init_even_column(Col_num, 0, Height, LN, []).

%%% init_X_column(Column_number, Row_number, Height, Left_neighbors, Initialized_cells)

%% starts first column (in plain order)
% first cell in first column
init_first_column(0, 0, Height, [], []) ->
  Pid = cell:init_cell(0, 0, #nbors{}),
  control ! {first, Pid},
  init_first_column(0, 1, Height, [], [Pid]);
% further cells in first column
init_first_column(0, Row_num, Height, [], [U | Initialized]) when Row_num < Height ->
  Pid = cell:init_cell(0, Row_num, #nbors{count = 1, upper = #neighbor{npid = U}}),
  init_first_column(0, Row_num + 1, Height, [], [Pid | [U | Initialized]]);
% all cell in the column already initialized, return list of them
init_first_column(0, _Row_num, _Height, [], Initialized) ->
  Initialized.

%% starts an even column (in plain order)
% first cell in column
init_even_column(Col_num, 0, Height, [UL | [LL | LN]], []) ->
  Pid = cell:init_cell(Col_num, 0, #nbors{count = 2, upper_left = #neighbor{npid = UL}, lower_left = #neighbor{npid = LL}}),
  init_even_column(Col_num, 1, Height, [LL | LN], [Pid]);
% further cells in column
init_even_column(Col_num, Row_num, Height, [UL | [LL | LN]], [U | Initialized]) ->
  Pid = cell:init_cell(Col_num, Row_num, #nbors{count = 3, upper = #neighbor{npid = U}, upper_left = #neighbor{npid = UL}, lower_left = #neighbor{npid = LL}}),
  init_even_column(Col_num, Row_num + 1, Height, [LL | LN], [Pid | [U | Initialized]]);
% all cell in the column already initialized, return list of them
init_even_column(Col_num, Row_num, _Height, [UL | []], [U | Initialized]) ->
  Pid = cell:init_cell(Col_num, Row_num, #nbors{count = 2, upper = #neighbor{npid = U}, upper_left = #neighbor{npid = UL}}),
  [Pid | [U | Initialized]].

%% starts an odd column, starts cells from last to first (descending order)
% last cell in column
init_odd_column(Col_num, Row_num, Height, [LL | [UL | LN]], []) ->
  Pid = cell:init_cell(Col_num, Row_num, #nbors{count = 2, lower_left = #neighbor{npid = LL}, upper_left = #neighbor{npid = UL}}),
  init_odd_column(Col_num, Row_num - 1, Height, [UL | LN], [Pid]);
% further cells in column
init_odd_column(Col_num, Row_num, Height, [LL | [UL | LN]], [L | Initialized]) ->
  Pid = cell:init_cell(Col_num, Row_num, #nbors{count = 3, lower_left = #neighbor{npid = LL}, upper_left = #neighbor{npid = UL}, lower = #neighbor{npid = L}}),
  init_odd_column(Col_num, Row_num - 1, Height, [UL | LN], [Pid | [L | Initialized]]);
% all cell in the column already initialized, return list of them
init_odd_column(Col_num, 0, _Height, [LL | []], [L | Initialized]) ->
  Pid = cell:init_cell(Col_num, 0, #nbors{count = 2, lower_left = #neighbor{npid = LL}, lower = #neighbor{npid = L}}),
  [Pid | [L | Initialized]].

